import React, { Component } from 'react';
import List from './components/List'
class App extends Component {
  /**
   * React 声明周期
   * 挂载
   * constructor
   * render  **
   * componentDidMount  ** 
   * 更新 
   * shouldComponentUpdate  
   * render ** 
   * componentDidUpdate  **
   * 销毁
   * componentWillUnmount
   * */
  handleCountAdd() {
    // const { count } = this.state

    
    // 将 setState() 视为请求而不是立即更新组件的命令。为了更好的感知性能，React 会延迟调用它，
    // 然后通过一次传递更新多个组件。React 并不会保证 state 的变更会立即生效。

    // setState() 的第二个参数为可选的回调函数，它将在 setState 完成合并并重新渲染组件后执行。
    // 通常，我们建议使用 componentDidUpdate() 来代替此方式。

    this.setState({
      count: count + 1
    }, () => {
      console.log(this.state);
    })

    // this.setState((state, props) => {
    //   return {
    //     count: state.count + 1
    //   }
    // }, () => {
    //   console.log(this.state);
    // })
    
  }

  handleSetMes = () => {
    this.setState({
      title: '今天下雨了'
    })
  }
  /**
   * @desc 如果不初始化 state 或不进行方法绑定，则不需要为 React 组件实现构造函数。
   * 
   * */
  constructor(props) {
    super(props)


    console.log(1);
    // 初始化 state
    this.state = {
      count: 1,
      mes: '哈哈哈哈哈'
    }

    console.log(this);
    // 方法绑定
    // this.handleCountAdd = this.handleCountAdd.bind(this)
  }

  // this 4种解决方法
  // 1. 在构造函数constructor 绑定方法
  //    this.handleClick = this.handleClick.bind(this)
  // 2. 合成事件绑定this
  //    <button onClick={ this.handleClick.bind(this) }></button>
  // 3. 合成事件箭头函数
  //    <button onClick={ () => this.handleClick() }></button>
  // 4. class filed 实现


  /*
    class {
      handleClick = () => {

      }
    }
  */

  /**
   * @desc render() 方法是 class 组件中唯一必须实现的方法。
   * @return  React 元素。通常通过 JSX 创建
   * */
  render() { 
    console.log(2);
    const { count, mes } = this.state
    return (
      <div>
        <h1>{count}</h1>
        <button onClick={ () => this.handleCountAdd() }>+1</button>
        <List mes={ mes } title={ '呵呵呵呵呵' } handleSetMes={ this.handleSetMes }></List>
      </div>
    );
  }
  /**
   * @desc componentDidMount() 会在组件挂载后（插入 DOM 树中）立即调用
   * 一般发起请求， 操作dom  调用setState
  */
  componentDidMount() {
    console.log(3);
  }
  /**
   * @desc 根据 shouldComponentUpdate() 的返回值，判断 React 组件的输出是否受当前 state 或 props 更改的影响。
   * @desc 默认行为是 state 每次发生变化组件都会重新渲染
   * 
   * 
  */
  // shouldComponentUpdate(nextProps, nextState) {
  //   console.log('变化后：', nextProps, nextState);
  //   console.log('变化前：', this.props, this.state);
  //   return true
  // }
  /**
   * @desc componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。
   * 
   * */ 
  componentDidUpdate(prevProps, prevState) {
    console.log('更新后',this.props, this.state);
    console.log('更新前', prevProps, prevState);
  }
}

export default App;
